package com.jiandian.service.impl;

import com.jiandian.dao.SignUserMapper;
import com.jiandian.entity.Activemember;
import com.jiandian.entity.SignLog;
import com.jiandian.entity.SignUser;
import com.jiandian.exception.ActivememberException;
import com.jiandian.exception.SignPrizeLogException;
import com.jiandian.page.PageInfo;
import com.jiandian.page.WhereMapUtil;
import com.jiandian.service.ActivememberService;
import com.jiandian.service.SignLogService;
import com.jiandian.service.SignUserService;
import com.jiandian.util.BeanUtils;
import com.jiandian.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;

/**
 * 签到用户
 *
 * @author houqi Fu
 * @date 2018/12/15
 */
@Service
@Slf4j
@Transactional
public class SignUserServiceImpl implements SignUserService {

    private static final Logger logger = LoggerFactory.getLogger(SignUserServiceImpl.class);

    @Autowired
    private SignUserMapper mapper;

    @Autowired
    private ActivememberService activememberService;

    @Autowired
    private SignLogService signLogService;

    @Override
    public SignUser add(SignUser record) {

        initBasicValue(record);

        int result = mapper.insert(record);
        if (result > 0) {
            return record;
        }
        return null;
    }

    @Override
    public SignUser update(SignUser record) {
        Integer id = record.getId();
        if (id == null) {
            return null;
        }
        SignUser dbSignUser = mapper.selectByPrimaryKey(id);
        if (dbSignUser == null) {
            return null;
        }
        BeanUtils.copyProperties(record, dbSignUser);
        // dbSignUser.setGmtModified(new Timestamp(System.currentTimeMillis()));
        int result = mapper.updateByPrimaryKey(dbSignUser);
        if (result > 0) {
            return dbSignUser;
        }
        return null;
    }

    @Override
    public SignUser findById(Integer id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public List<SignUser> findAll(PageInfo pageInfo) {
        return mapper.selectAll(pageInfo);
    }

    @Override
    public int selectCount(PageInfo pageInfo) {
        return mapper.selectCount(pageInfo);
    }

    @Override
    public int batchInsert(List<SignUser> list) {
        for (SignUser bean : list) {
            initBasicValue(bean);
        }
        return mapper.batchInsert(list);
    }

    @Override
    public List<SignUser> batchQueryByIds(List<Integer> ids) {
        return mapper.batchQueryByIds(ids);
    }

    @Override
    public int delete(Integer id) {
        return mapper.deleteByPrimaryKey(id);
    }

    @Override
    public int delete(SignUser record) {
        return delete(record.getId());
    }

    @Override
    public int batchDeleteById(List<Integer> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            return mapper.batchDeleteById(ids);
        }
        return 0;
    }

    @Override
    public PageInfo getPage(SignUser whereEntity, PageInfo pageInfo) {
        pageInfo.setWhereMap(WhereMapUtil.convertBeanToWhereMap(whereEntity));
        pageInfo.setTotalRecord(selectCount(pageInfo));
        pageInfo.queryPageResult(pageInfo);
        pageInfo.setResultObject(findAll(pageInfo));
        return pageInfo;
    }

    @Override
    public SignUser getAndInsertByMachineNumber(String machineNumber) {
        // 查询上机人员信息
        Activemember activemember = activememberService.findByMachineNumber(machineNumber);
        if (activemember == null) {
            throw new ActivememberException("未查询到上机machineNumber为" + machineNumber + "的人员");
        }
        // 向签到用户表中插入或更新用户信息
        SignUser signUser = new SignUser();
        signUser.setIdNumber(activemember.getIdnumber());
        signUser.setName(activemember.getName());
        signUser.setMemberId(activemember.getMemberid());

        return insertOrUpdate(signUser);
    }

    @Override
    public SignUser insertOrUpdate(SignUser signUser) {
        SignUser selectByIdNumber = selectByIdNumber(signUser.getIdNumber());
        if (selectByIdNumber == null) {
            // 如果表中不存在此用户信息，则初始化
            initBasicValue(signUser);
            return add(signUser);
        } else {
            return selectByIdNumber;
        }

    }

    @Override
    public SignUser selectByIdNumber(String idNumber) {
        return mapper.selectByIdNumber(idNumber);
    }

    @Override
    @Transient
    public String signinByIdAndMachineNumber(Integer id, String machineNumber) {
        SignUser signUser = mapper.selectByPrimaryKey(id);

        if (checkIfSignToday(signUser.getId())) {
            throw new SignPrizeLogException("今天已签到过");
            // return "今天已签到过";
        }
        try {
            // 记录日志
            SignLog signLog = new SignLog();
            signLog.setUserId(id);
            signLog.setSignMachine(machineNumber);
            signLogService.add(signLog);
            // 设置签到状态
            int continueSignDays = signLogService.clacContinueSignDays(signUser.getId());
            signUser.setSignCount(continueSignDays);

            signUser.setIfSignin(true);
            signUser.setPrizeTimes(signUser.getPrizeTimes() + 1);
            mapper.updateByPrimaryKey(signUser);
        } catch (Exception e) {
            throw new SignPrizeLogException("签到出错,请联系管理员");
            // return "签到出错";
        }
        return "签到成功";
    }

    @Override
    public void initDailyData() {
        log.info("初始化抽奖次数、今天签到标示");
        mapper.initDailyData();
    }

    @Override
    public boolean supple(SignUser signUser) {
        LinkedList<LocalDate> localDates = new LinkedList<>();
        // 所有连续签到天数的中断天数
        LinkedList<Integer> interruptCount = new LinkedList<>();
        Integer supplementCount = signUser.getSupplementCount();

        if (supplementCount == 0) {
            throw new SignPrizeLogException("您无补签卡");
        }

        List<SignLog> signLogs = signLogService.selectByUserId(signUser.getId());

        if (signLogs.size() == 0) {
            throw new SignPrizeLogException("您无签到记录，无法使用补签卡");
        }

        SignLog lastSignLog = signLogs.get(0);
        LocalDate lastSignLogDate = lastSignLog.getCreateTime().toLocalDateTime().toLocalDate();

        // 判断最后一次签到日期到目前的天数差，如果大于1说明最后一次是断签的,从这开始补充

        if (!checkIfSignToday(signUser.getId())) {
            throw new SignPrizeLogException("请先签到后，再使用补签卡");
        }
        SignUser preUpdateSignUser = null;

        for (SignLog signLog : signLogs) {
            Timestamp createTime = signLog.getCreateTime();
            LocalDate localDate = createTime.toLocalDateTime().toLocalDate();
            localDates.add(localDate);
            if (localDates.size() == 2) {
                LocalDate pop = localDates.pop();
                long intervalDays = DateUtil.calcIntervalDays(localDate, pop);
                // 如果是连续的两天
                if (intervalDays > 1L) {
                    interruptCount.add((int) intervalDays);
                    // 当相差天数为2时，需要使用1张补签卡，这里减去1
                    preUpdateSignUser = signLogService.consumeSupplement(signUser, (int) intervalDays - 1, supplementCount, pop);

                }
            }
        }
        // 如果没有断签记录，那么使用补签卡时，则从签到第一天开始，向之前的日期增加签到记录
        if (interruptCount.size() == 0) {
            preUpdateSignUser = signLogService.consumeSupplement(signUser, supplementCount, supplementCount, localDates.get(0));
        }

        int continueSignDays = signLogService.clacContinueSignDays(signUser.getId());
        signUser.setSignCount(continueSignDays);
        mapper.updateByPrimaryKey(preUpdateSignUser);
        return true;
    }

    private void initBasicValue(SignUser signUser) {
        signUser.setIfSignin(false);
        signUser.setSupplementCount(0);
        signUser.setUsedSupplementCount(0);
        signUser.setPrizeTimes(0);
        signUser.setSignCount(0);
        signUser.setPrePrize(-1);
    }

    @Override
    public boolean checkIfRemainSupplement(SignUser signUser) {

        if (getSupplementCount(signUser.getId()) > 0) {
            return true;
        }
        return false;
    }

    @Override
    public int getSupplementCount(int userId) {
        return mapper.getSupplementCount(userId);
    }

    @Override
    public boolean checkIfSignToday(int userId) {
        SignLog lastSignDay = signLogService.getLastSignDay(userId);
        if (lastSignDay == null) {
            return false;
        }
        boolean ifToday = DateUtil.calcIntervalDays(LocalDate.now(), DateUtil.timestampToLocalDate(lastSignDay.getCreateTime())) == 0;
        if (ifToday) {
            return true;
        }
        return false;
    }
}
